package com.wlyuan.open.scanner.repository.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wlyuan.open.scanner.constant.Constants;
import com.wlyuan.open.scanner.dao.entity.PriceOrderCacheDO;
import com.wlyuan.open.scanner.dao.mapper.PriceDocIndexMapper;
import com.wlyuan.open.scanner.dao.mapper.PriceOrderCacheMapper;
import com.wlyuan.open.scanner.domain.quotation.QuotationDetailConvert;
import com.wlyuan.open.scanner.domain.quotation.QuotationMatch;
import com.wlyuan.open.scanner.repository.PriceOrderCacheRepository;
import com.wlyuan.open.scanner.utils.NumberUtils;
import com.wlyuan.open.scanner.utils.StreamUtils;
import com.wlyuan.open.scanner.utils.enums.quotation.*;
import com.wlyuan.open.utils.LongUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import lombok.var;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * @author lijing
 * @description
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class PriceOrderCacheRepositoryImpl implements PriceOrderCacheRepository {
    private final PriceOrderCacheMapper priceOrdercacheMapper;
    private final PriceDocIndexMapper priceDocindexMapper;

    @Override
    public BigDecimal getExceptionCost(Long orderId) {
        return priceOrdercacheMapper.getExceptionCost(orderId);
    }

    @Override
    public List<PriceOrderCacheDO> getByOrderId(Long orderId) {
        LambdaQueryWrapper<PriceOrderCacheDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PriceOrderCacheDO::getCacheOrderid, orderId).eq(PriceOrderCacheDO::getCacheInvalid, Constants.INVALID_NUMBER_ZERO);
        return priceOrdercacheMapper.selectList(queryWrapper);
    }

    @Override
    public boolean checkQuotation(Long orderId) {
        return CollectionUtils.isEmpty(getByOrderId(orderId));
    }

    @Override
    public List<PriceOrderCacheDO> getAdditionByOrderId(Long orderId) {
        LambdaQueryWrapper<PriceOrderCacheDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(PriceOrderCacheDO::getCacheOrderid, orderId)
                .eq(PriceOrderCacheDO::getCacheInvalid, Constants.INVALID_NUMBER_ZERO)
                .eq(PriceOrderCacheDO::getCacheType, QuotationDetailTypeEnum.ADDITION.getValue())
                .eq(PriceOrderCacheDO::getCacheIsaddition, 1);
        return priceOrdercacheMapper.selectList(queryWrapper);
    }

    @Override
    public QuotationMatch getMatchInfo(Long orderId) {
        var list = priceOrdercacheMapper.getMatchInfo(orderId);
        if (!CollectionUtils.isEmpty(list)) {
            QuotationMatch match = new QuotationMatch();
            //运输费 整车 + 零担
            var transportFee = priceMatch(list, x -> QuotationDetailTypeEnum.FULL_LOAD.getValue().equals(x.getCacheType()) || QuotationDetailTypeEnum.LESS_LOAD.getValue().equals(x.getCacheType()));
            //装货费
            var loadFee = priceMatch(list, x -> QuotationDetailTypeEnum.ON_LOAD.getValue().equals(x.getCacheType()));
            //卸货费
            var unLoadFee = priceMatch(list, x -> QuotationDetailTypeEnum.OFF_LOAD.getValue().equals(x.getCacheType()));
            //提货费
            var pickFee = priceMatch(list, x -> QuotationDetailTypeEnum.PICK.getValue().equals(x.getCacheType()));
            //送货费
            var deliverFee = priceMatch(list, x -> QuotationDetailTypeEnum.DELIVERY.getValue().equals(x.getCacheType()));
            //预付款
            var prepayFee = priceMatch(list, x -> QuotationDetailTypeEnum.PAYMENT.getValue().equals(x.getCacheType()));
            //到付款
            var arrivePayFee = priceMatch(list, x -> QuotationDetailTypeEnum.PAYABLE.getValue().equals(x.getCacheType()));
            //代收货款
            var collectionFee = priceMatch(list, x -> QuotationDetailTypeEnum.COLLECTION.getValue().equals(x.getCacheType()));
            //最低费用
            var minFee = priceMatch(list, x -> QuotationDetailTypeEnum.MIN.getValue().equals(x.getCacheType()));
            //保险费
            var insureFee = priceMatch(list, x -> QuotationDetailTypeEnum.INSURANCE.getValue().equals(x.getCacheType()));
            //税费
            var taxFee = priceMatch(list, x -> QuotationDetailTypeEnum.TAX.getValue().equals(x.getCacheType()));
            match.setTransportFee(transportFee);
            match.setLoadFee(loadFee);
            match.setUnloadFee(unLoadFee);
            match.setPickFee(pickFee);
            match.setDeliverFee(deliverFee);
            match.setPrepayFee(prepayFee);
            match.setArrivePayFee(arrivePayFee);
            match.setCollectionFee(collectionFee);
            match.setMinimumFee(minFee);
            match.setInsureFee(insureFee);
            match.setTaxFee(taxFee);
            match.setOrderId(orderId);
            match.setStatus(TemplateStatusEnum.AGREE.getValue().longValue());
            var data = list.stream().findFirst().get();
            match.setCreateAt(data.getCacheInserttime());
            match.setCreateBy(data.getCacheAuthor());
            match.setUpdateAt(data.getCacheUpdatetime());
            match.setUpdateBy(data.getCacheUpdater());
            match.setMatchAt(data.getCacheInserttime());
            match.setTenantId(data.getTenantId());
            match.setTemplateId(data.getCacheDocid());
            match.setRemarks(data.getRemarks());
            match.setRefresh(data.getRefresh() == null ? Constants.INVALID_NUMBER_ZERO : data.getRefresh());
            //是价格重算 手动
            match.setMode(TemplateMatchModeEnum.fromValue(match.getRefresh()).getNewValue());
            //附加费用
            match.setSurchargeFees(QuotationDetailConvert.convertOrderCacheSurcharge(getAdditionByOrderId(orderId)));
            return match;
        }
        return null;
    }

    @Override
    public QuotationMatch getNoAdditionMatchInfo(Long orderId) {
        var list = priceOrdercacheMapper.getNoAdditionMatchInfo(orderId);
        if (!CollectionUtils.isEmpty(list)) {
            QuotationMatch match = new QuotationMatch();
            //运输费 整车 + 零担
            var transportFee = priceMatch(list, x -> QuotationDetailTypeEnum.FULL_LOAD.getValue().equals(x.getCacheType()) || QuotationDetailTypeEnum.LESS_LOAD.getValue().equals(x.getCacheType()));
            //装货费
            var loadFee = priceMatch(list, x -> QuotationDetailTypeEnum.ON_LOAD.getValue().equals(x.getCacheType()));
            //卸货费
            var unLoadFee = priceMatch(list, x -> QuotationDetailTypeEnum.OFF_LOAD.getValue().equals(x.getCacheType()));
            //提货费
            var pickFee = priceMatch(list, x -> QuotationDetailTypeEnum.PICK.getValue().equals(x.getCacheType()));
            //送货费
            var deliverFee = priceMatch(list, x -> QuotationDetailTypeEnum.DELIVERY.getValue().equals(x.getCacheType()));
            //预付款
            var prepayFee = priceMatch(list, x -> QuotationDetailTypeEnum.PAYMENT.getValue().equals(x.getCacheType()));
            //到付款
            var arrivePayFee = priceMatch(list, x -> QuotationDetailTypeEnum.PAYABLE.getValue().equals(x.getCacheType()));
            //代收货款
            var collectionFee = priceMatch(list, x -> QuotationDetailTypeEnum.COLLECTION.getValue().equals(x.getCacheType()));
            //最低费用
            var minFee = priceMatch(list, x -> QuotationDetailTypeEnum.MIN.getValue().equals(x.getCacheType()));
            //保险费
            var insureFee = priceMatch(list, x -> QuotationDetailTypeEnum.INSURANCE.getValue().equals(x.getCacheType()));
            //税费
            var taxFee = priceMatch(list, x -> QuotationDetailTypeEnum.TAX.getValue().equals(x.getCacheType()));
            match.setTransportFee(transportFee);
            match.setLoadFee(loadFee);
            match.setUnloadFee(unLoadFee);
            match.setPickFee(pickFee);
            match.setDeliverFee(deliverFee);
            match.setPrepayFee(prepayFee);
            match.setArrivePayFee(arrivePayFee);
            match.setCollectionFee(collectionFee);
            match.setMinimumFee(minFee);
            match.setInsureFee(insureFee);
            match.setTaxFee(taxFee);
            match.setOrderId(orderId);
            match.setStatus(TemplateStatusEnum.AGREE.getValue().longValue());
            var data = list.stream().findFirst().get();
            match.setCreateAt(data.getCacheInserttime());
            match.setCreateBy(data.getCacheAuthor());
            match.setUpdateAt(data.getCacheUpdatetime());
            match.setUpdateBy(data.getCacheUpdater());
            match.setMatchAt(data.getCacheInserttime());
            match.setTemplateId(data.getCacheDocid());
            match.setRefresh(data.getRefresh() == null ? Constants.INVALID_NUMBER_ZERO : data.getRefresh());
            //是价格重算 手动
            match.setMode(TemplateMatchModeEnum.fromValue(match.getRefresh()).getNewValue());
            //租户取值问题
            match.setTenantId(data.getTenantId());
            match.setRemarks(data.getCacheComments());
            //报价类型
            match.setType(QuotationTypeEnum.TEMPLATE_QUOTE.getValue());
            if (LongUtils.notNullLong(data.getCacheDocid())) {
                Optional.ofNullable(priceDocindexMapper.getById(data.getCacheDocid())).ifPresent(t -> {
                    match.setTenantId(t.getIndexCreatorcompanyid());
                    match.setRemarks(t.getIndexDescription());
                    //按单报价如果已过关账期,则类型需要为按单报价
                    if (TemplateTypeEnum.isQuote(t.getIndexType()) || TemplateTypeEnum.isCombineQuote(t.getIndexType())) {
                        match.setType(QuotationTypeEnum.COMMON_QUOTE.getValue());
                    }
                    //补充报价类型
                    if (TemplateTypeEnum.isAddQuote(t.getIndexType()) || TemplateTypeEnum.isCombineAddQuote(t.getIndexType())) {
                        match.setType(QuotationTypeEnum.ADD_QUOTE.getValue());
                    }
                });
            }
            //附加费用
            //match.setSurchargeFees(QuotationDetailConvert.convertOrderCacheSurcharge(getAdditionByOrderId(orderId)));
            return match;
        }
        return null;
    }

    private BigDecimal priceMatch(List<PriceOrderCacheDO> list, Predicate<PriceOrderCacheDO> predicate) {
        list = list.stream().map(x -> {
            x.setCacheAmount(NumberUtils.changeZero(x.getCacheAmount()));
            return x;
        }).collect(Collectors.toList());
        return StreamUtils.sum(list.stream().filter(predicate).collect(Collectors.toList()), PriceOrderCacheDO::getCacheAmount, BigDecimal::add, BigDecimal.ZERO);
    }
}
